package work.mediway.mdm.biz.bo;

import com.mediway.hos.common.config.DmpBaseConfig;
import com.mediway.hos.common.core.redis.RedisCache;
import com.mediway.hos.common.utils.spring.SpringUtils;

import java.sql.Connection;
import java.util.List;
import java.util.stream.Collectors;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.text.StrPool;
import cn.hutool.core.util.StrUtil;
import lombok.Data;
import work.mediway.mdm.core.constant.MdmConstant;
import work.mediway.mdm.core.exception.BizException;
import work.mediway.mdm.core.exception.DataException;
import work.mediway.mdm.biz.entity.biz.SsDataQualityConfig;
import work.mediway.mdm.biz.entity.biz.SsDataQualityConfigItem;
import work.mediway.mdm.biz.entity.biz.SsDataQualityLog;

import static work.mediway.mdm.core.constant.MdmConstant.RedisConst.DATA_QUALITY_COMPARE_TABLE_LIST;

/**
 * 数据连接与配置
 *
 * @author zhongyj <1126834403@qq.com><br/>
 * @date 2022/7/18
 */
@Data
public class DataQualityConnectionBO {

    /**
     * 记录id
     */
    private String logId;

    /**
     * 源数据库连接
     */
    private Connection sourceConnection;

    /**
     * 目标数据库连接
     */
    private Connection targetConnection;

    /**
     * 是否为主数据
     */
    private boolean isMdm;

    /**
     * 唯一值配置信息
     */
    private SsDataQualityConfigItem dataQualityConfigItemUnique;

    /**
     * 配置信息
     */
    private SsDataQualityConfig dataQualityConfig;

    /**
     * 结果信息
     */
    private SsDataQualityLog ssDataQualityLog;

    /**
     * 缓存使用
     */
    private String key;

    /**
     * 获取源系统所有比对字段
     *
     * @return List<String>
     */
    public List<String> getAllSourceField() {
        return this.getDataQualityConfig().getDataQualityConfigItems().stream().map(SsDataQualityConfigItem::getSourceSystemField).sorted().collect(Collectors.toList());
    }

    /**
     * 获取源系统所有比对字段
     *
     * @return List<String>
     */
    public List<String> getAllTargetField() {
        return this.getDataQualityConfig().getDataQualityConfigItems().stream().map(SsDataQualityConfigItem::getTargetSystemField).sorted().collect(Collectors.toList());
    }

    // TODO: 2022/10/6
    public Connection getSourceConnection() {
//        return SpringUtils.getBean(BaseDatabaseHelper.class).getConnectionByDatabaseId(Long.valueOf(dataQualityConfig.getSourceAccessSystemId()));
        return null;
    }

    public Connection getTargetConnection() {
//        return SpringUtils.getBean(BaseDatabaseHelper.class).getConnectionByDatabaseId(Long.valueOf(dataQualityConfig.getTargetAccessSystemId()));
        return null;
    }

    public String getSourceSchemaTable() {
        return StrUtil.isBlank(dataQualityConfig.getSourceSchemaName()) ? dataQualityConfig.getSourceTableCode() : dataQualityConfig.getSourceSchemaName() + StrPool.DOT + dataQualityConfig.getSourceTableCode();
    }

    public String getTargetSchemaTable() {
        return StrUtil.isBlank(dataQualityConfig.getTargetSchemaName()) ? dataQualityConfig.getTargetTableCode() : dataQualityConfig.getTargetSchemaName() + StrPool.DOT + dataQualityConfig.getTargetTableCode();
    }


    public String buildSourceSelectSql(List<String> val) {
        StringBuilder selectSql = new StringBuilder("SELECT ")
                .append(this.getDataQualityConfigItemUnique().getSourceSystemField())
                .append(" FROM ").append(this.getSourceSchemaTable());
        if (CollUtil.isNotEmpty(val)) {
            List<String> tmp = CollUtil.newArrayList();
            val.forEach(v -> tmp.add("'" + val + "'"));
            selectSql.append(" WHERE ").append(this.getDataQualityConfigItemUnique().getSourceSystemField())
                    .append(" IN (").append(StrUtil.join(",", tmp)).append(" )");
        }
        return selectSql.toString();
    }

    public String buildSourceSelectSql(List<String> val, List<String> sourceFields) {
        if (CollUtil.isEmpty(sourceFields)) {
            throw new DataException("构建查询源系统数据SQL, 查询字段不能为空, sourceFields = " + sourceFields);
        }
        StringBuilder selectSql = new StringBuilder("SELECT ")
                .append(StrUtil.join(StrUtil.COMMA, sourceFields))
                .append(" FROM ").append(this.getSourceSchemaTable());
        if (CollUtil.isNotEmpty(val)) {
            List<String> tmp = CollUtil.newArrayList();
            val.forEach(v -> tmp.add("'" + val + "'"));
            selectSql.append(" WHERE ").append(this.getDataQualityConfigItemUnique().getSourceSystemField())
                    .append(" IN (").append(StrUtil.join(",", tmp)).append(" )");
        }
        return selectSql.toString();
    }

    public String buildTargetSelectSql(List<String> val) {
        StringBuilder selectSql = new StringBuilder("SELECT ")
                .append(this.getDataQualityConfigItemUnique().getTargetSystemField())
                .append(" FROM ").append(this.getTargetSchemaTable());
        if (CollUtil.isNotEmpty(val)) {
            List<String> tmp = CollUtil.newArrayList();
            val.forEach(v -> tmp.add("'" + val + "'"));
            selectSql.append(" WHERE ").append(this.getDataQualityConfigItemUnique().getTargetSystemField())
                    .append(" IN (").append(StrUtil.join(",", tmp)).append(" )");
        }
        return selectSql.toString();
    }

    public String buildTmpFile(String tableCode, long pos, int origin) {
        String path = StrUtil.removeSuffix(DmpBaseConfig.getProfile(), "/uploadPath")
                + "/data_quality/" + (origin == 0 ? "source/" : "target/") + tableCode + "/"
                + this.getLogId() + "-" + tableCode + "-" + pos + ".txt";
        FileUtil.touch(path);
        return path;
    }

    public void checkCompareTableExist() {
        List<String> comparingTables = SpringUtils.getBean(RedisCache.class).getCacheList(DATA_QUALITY_COMPARE_TABLE_LIST);
        String value = StrUtil.join(StrUtil.DASHED, this.getDataQualityConfig().getTargetAccessSystem(), this.getTargetSchemaTable());
        if (CollUtil.contains(comparingTables, value)) {
            throw new BizException(StrUtil.format("当前表正在比对, 请勿重复提交"));
        } else {
            SpringUtils.getBean(RedisCache.class).setCacheList(DATA_QUALITY_COMPARE_TABLE_LIST, CollUtil.newArrayList(value));
        }
    }

    public void clearComparingTable() {
        List<String> comparingTables = SpringUtils.getBean(RedisCache.class).getCacheList(DATA_QUALITY_COMPARE_TABLE_LIST);
        String value = StrUtil.join(StrUtil.DASHED, this.getDataQualityConfig().getTargetAccessSystem(), this.getTargetSchemaTable());
        if (CollUtil.contains(comparingTables, value)) {
            List<String> removeAny = CollUtil.removeAny(comparingTables, value);
            SpringUtils.getBean(RedisCache.class).deleteObject(DATA_QUALITY_COMPARE_TABLE_LIST);
            if (CollUtil.isNotEmpty(removeAny)) {
                SpringUtils.getBean(RedisCache.class).setCacheList(DATA_QUALITY_COMPARE_TABLE_LIST, removeAny);
            }
        }
    }

    // ====================================================== 内容比对key ====================================================== //

    /**
     * 内容比对时源系统缓存key
     *
     * @return String
     */
    public String buildSourceContentCacheKeyList() {
        return StrUtil.format(MdmConstant.RedisConst.DATA_QUALITY_SOURCE_CACHE_C, dataQualityConfig.getSourceTableCode(), getKey());
    }

    /**
     * 内容比对时目标系统缓存key
     *
     * @return String
     */
    public String buildTargetContentCacheKeyList() {
        return StrUtil.format(MdmConstant.RedisConst.DATA_QUALITY_TARGET_CACHE_C, dataQualityConfig.getTargetTableCode(), getKey());
    }

    /**
     * 内容比对时源系统唯一值缓存key
     *
     * @param val String
     * @return String
     */
    public String buildSourceUniqueMapCacheKeyC(String val) {
        return StrUtil.format(MdmConstant.RedisConst.DATA_QUALITY_SOURCE_CACHE_UNIQUE_C, dataQualityConfig.getSourceTableCode(), getKey(), dataQualityConfigItemUnique.getSourceSystemField() + val);
    }

    /**
     * 内容比对时目标系统唯一值缓存key
     *
     * @param val String
     * @return String
     */
    public String buildTargetUniqueMapCacheKeyC(String val) {
        return StrUtil.format(MdmConstant.RedisConst.DATA_QUALITY_TARGET_CACHE_UNIQUE_C, dataQualityConfig.getTargetTableCode(), getKey(), dataQualityConfigItemUnique.getTargetSystemField() + val);
    }

}
